#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>

#include <fstream>
#include <iostream>
#include <string>
#include <unordered_map>
#include <fmt/core.h>
#include "attrs.h"


using namespace std;
using fmt::format;

int slot = 0;
ofstream ofs;
unordered_map<int, string> ump; // <时隙：待执行命令>

void execute_script(int signo) {
    uint64_t now = get_time_ns(), end;

    ofs << format("当前时隙：{}，Now：{}", slot, now);
    if (ump.find(slot) != ump.end()) {
        system(ump[slot].c_str());
    }

    end = get_time_ns();
    ofs << format("，执行命令用时：{} us\n", (end - now)/1000);
    ofs.flush();
    slot++;
}

void read_file(string &filename) {
    int idx, tslot;
    string line, cmd;
    ifstream infile;
    infile.open(filename);

    while(getline(infile, line)) {
        if (line.size() > 6) {
            idx = line.find(":");
            tslot = stoi(line.substr(0, idx));
            cmd = line.substr(idx + 1);
            ump[tslot] = cmd;
        }
    }
    infile.close();
}

int main(int args, char *argv[]) {
    string logfile, linkfile;
    struct timespec ts;
    long long start;

    if (args < 3) {
        cout << "./docker_run 节点ID， 起始时刻\n";
        cout << "参数不足，指定文件名：1101，起始时刻：1652163656\n";
        exit(EXIT_FAILURE);
    }

    /* 起始时刻（s） */
    start = atol(argv[2]);

    /* 打开日志文件 */
    logfile = format(DOCKER_LOGFILE, argv[1]);
    ofs.open(logfile, ios::out | ios::trunc );

    /* 读取链路更新信息，需要执行的命令 */
    linkfile = format(LINK_FILE, argv[1]);
    read_file(linkfile);

    /* 第0s马上执行，第1s才在指定的时刻开始 */
    execute_script(0);

    /* 设置定时器起始时刻、每秒执行 */
    clock_gettime(CLOCK_REALTIME, &ts);
    signal(SIGALRM, execute_script); // 注册信号的处理函数
    struct itimerval iter;
    iter.it_interval.tv_sec = 1;
    iter.it_interval.tv_usec = 0;
    iter.it_value.tv_sec = start - ts.tv_sec - 1;
    iter.it_value.tv_usec = 1000000ULL - ts.tv_nsec/1000;
    setitimer(ITIMER_REAL, &iter, NULL);

    while(slot < 6020) {
        pause();    // 等待信号
    }

    ofs.close();
    return 0;
}


